#include "git2updater.h"
#include "source/versioninfo.h"
#include <QDebug>
#include <QMetaObject>
#include <QDateTime>
#include <QProcess>
#include <qcoreapplication.h>
#include <QFile>

Git2Updater::Git2Updater(QObject *parent) : QObject(parent)
{
}

Git2Updater::~Git2Updater()
{
    git_libgit2_shutdown();
}

void Git2Updater::init()
{
    git_libgit2_init();
    qDebug() << "git_libgit2 initialized";
}

void Git2Updater::reportError(const git_error *e)
{
    qDebug() << "Error:" << e->message;
    QVariantMap result;
    result["error"] = e->message;
    emit response(false, result);
}

bool Git2Updater::openRepository(const QString &path, git_repository **repo)
{
    int error = git_repository_open(repo, path.toStdString().c_str());
    if (error != 0) {
        reportError(giterr_last());
        return false;
    }
    return true;
}

bool Git2Updater::lookupRemote(git_repository *repo, git_remote **remote)
{
    int error = git_remote_lookup(remote, repo, "origin");
    if (error != 0) {
        reportError(giterr_last());
        return false;
    }
    return true;
}

void Git2Updater::fetchRepository(const QString &path)
{
    qDebug() << "Starting fetchRepository for path:" << path;

    git_repository *repo = nullptr;
    git_remote *remote = nullptr;

    if (!openRepository(path, &repo)) return;
    if (!lookupRemote(repo, &remote)) {
        git_repository_free(repo);
        return;
    }

    git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
    fetch_opts.callbacks.transfer_progress = [](const git_transfer_progress *stats, void *payload) {
        Git2Updater *self = static_cast<Git2Updater*>(payload);
        int percent = (100 * stats->received_objects) / stats->total_objects;
        QMetaObject::invokeMethod(self, [=]() {
            qDebug() << "percent:" << percent;
            emit self->updateProgress(percent);
        });
        return 0;
    };
    fetch_opts.callbacks.payload = this;

    if (git_remote_fetch(remote, nullptr, &fetch_opts, nullptr) != 0) {
        reportError(giterr_last());
    } else {
        QVariantMap result;
        result["message"] = "Fetch completed successfully";
        emit response(true, result);
    }

    git_remote_free(remote);
    git_repository_free(repo);
}

void Git2Updater::resetToRemote(const QString &path)
{
    qDebug() << "Starting resetToRemote for path:" << path;

    QString exceptionFilePath = "/tmp/qt_app_update";
    QFile file(exceptionFilePath);

    QVariantMap result;

    // 尝试打开文件，如果文件不存在则创建，如果存在则覆盖
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream out(&file);
        out << "This is a test content.";  // 写入内容
        file.close();  // 完成写入后关闭文件

        result["message"] = "更新成功";
        emit response(true, result);
    } else {
        QString err = file.errorString();
        qDebug() << "Failed to create file. Error:" << err;
        result["error"] = "更新失败:" + err;
        emit response(false, result);
    }


    // QString exceptionFilePath = "/tmp/qt_app_update";

    // // 使用QProcess执行命令来删除异常文件
    // QProcess process;
    // QStringList arguments;
    // arguments << "-c" << QString("touch -f %1").arg(exceptionFilePath);

    // process.start("/bin/bash", arguments);
    // process.waitForFinished(); // 等待命令执行完成

    // QString program = "/bin/bash";
    // QStringList arguments;
    // arguments << "/home/ASuser/fix.sh";

    // // 启动分离的进程，执行更新脚本
    // bool success = QProcess::startDetached(program, arguments);

    // // 退出Qt应用，避免因服务停止而崩溃
    // QCoreApplication::quit();

    // git_repository *repo = nullptr;
    // git_object *target = nullptr;

    // if (!openRepository(path, &repo))
    // {
    //     qDebug() << "Error:" << "无法打开目标文件夹";
    //     QVariantMap result;
    //     result["error"] = "无法打开目标文件夹";
    //     emit response(false, result);
    //     return;
    // }

    // if (git_revparse_single(&target, repo, "refs/remotes/origin/master") != 0) {
    //     reportError(giterr_last());
    //     git_repository_free(repo);
    //     return;
    // }

    // if (git_reset(repo, target, GIT_RESET_HARD, nullptr) != 0) {
    //     reportError(giterr_last());
    // } else {
    //     QVariantMap result;
    //     result["message"] = "Repository reset to remote successfully";
    //     emit response(true, result);
    // }

    // git_object_free(target);
    // git_repository_free(repo);
}

void Git2Updater::getLatestVersionInfo()
{
    qDebug() << "Starting getLatestVersionInfo";

    git_repository *repo = nullptr;
    git_remote *remote = nullptr;

    if (!openRepository(repoPath, &repo))
    {
        reportError(giterr_last());
        return;
    }
    if (!lookupRemote(repo, &remote)) {
        reportError(giterr_last());
        git_repository_free(repo);
        return;
    }

    git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;

    fetch_opts.callbacks.transfer_progress = [](const git_transfer_progress *stats, void *payload) {
        Git2Updater *self = static_cast<Git2Updater*>(payload);
        int percent = (100 * stats->received_objects) / stats->total_objects;
        QMetaObject::invokeMethod(self, [=]() {
            qDebug() << "percent:" << percent;
            emit self->updateProgress(percent);
        });
        return 0;
    };
    fetch_opts.callbacks.payload = this;

    char *strs[1];
    git_strarray refspecs;
    strs[0] = "refs/heads/master";  // 定义一个字符串数组，包含你要拉取的分支
    refspecs.count = 1;  // 数组中有 1 个元素
    refspecs.strings = strs;  // 直接赋值，不需要转换
    if (git_remote_fetch(remote, &refspecs, &fetch_opts, nullptr) != 0) {
        reportError(giterr_last());
        git_remote_free(remote);
        git_repository_free(repo);
        return;
    }

    git_oid oid;
    if (git_reference_name_to_id(&oid, repo, "refs/remotes/origin/master") != 0) {
        reportError(giterr_last());
        git_remote_free(remote);
        git_repository_free(repo);
        return;
    }



    git_commit *commit = nullptr;
    if (git_commit_lookup(&commit, repo, &oid) != 0) {
        reportError(giterr_last());
        git_remote_free(remote);
        git_repository_free(repo);
        return;
    }

    const char *message = git_commit_message(commit);
    const git_signature *author = git_commit_author(commit);
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(author->when.time);
    QString formattedDate = dateTime.toString(Qt::ISODate);

    QStringList messageLines = QString::fromUtf8(message).split('\n');
    QString version = messageLines.takeFirst().trimmed(); // 获取第一行作为版本号
    QString description = messageLines.join('\n').trimmed(); // 去掉第一行后的详细信息


    QVariantMap result;
    const char* id_str = reinterpret_cast<const char*>(git_commit_id(commit)->id);

    result["version"] = version;
    result["description"] = description;
    result["date"] = formattedDate;

    QString latestVersion = getCurrentVersion(); // 示例版本号
    result["isupdate"] = (version != latestVersion);

    qDebug() << "getLatestVersionInfo result:" << result <<
        "current :" << latestVersion;
    emit response(true, result);

    git_commit_free(commit);
    git_remote_free(remote);
    git_repository_free(repo);
}

void Git2Updater::fetchLatestTagInfo(git_repository *repo)
{
    git_oid oid;
    if (git_reference_name_to_id(&oid, repo, "refs/tags/latest") != 0) {
        reportError(giterr_last());
        return;
    }

    git_tag *tag = nullptr;
    if (git_tag_lookup(&tag, repo, &oid) != 0) {
        reportError(giterr_last());
        return;
    }

    const git_signature *tagger = git_tag_tagger(tag);
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(tagger->when.time);
    QString formattedDate = dateTime.toString(Qt::ISODate);

    QVariantMap result;
    result["version"] = QString::fromUtf8(git_tag_name(tag));
    result["description"] = QString::fromUtf8(git_tag_message(tag));
    result["date"] = formattedDate;

    emit response(true, result);

    git_tag_free(tag);
}

void Git2Updater::startUpdate()
{
    qDebug() << "Starting update for repository at:" << repoPath;
    //fetchRepository(repoPath);
    resetToRemote(repoPath);
    qDebug() << "Update process completed";
}
